package top.ysez.controller;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author YsEz
 * @version V1.0.0
 * @date 2022/7/5 22:22
 *     <p>ThreadPoolExecutor 的7个参数 ThreadPoolExecutor (int corePoolSize, //核心线程数 int
 *     maximumPoolSize, //最大线程数 long keepAliveTime, //线程的空闲时间 TimeUnit unit, //空闲时间的单位(时分秒等)
 *     BlockingQueue<Runnable> workQueue, //等待队列 ThreadFactory threadFactory, //线程工厂
 *     RejectedExecutionHandler handler) //拒绝策略:抛出,提交自执行,丢弃,丢弃最久
 */
@Slf4j
public class Thread04 {
  private static volatile boolean flag = true;
  // volatile 轻量级的同步机制
  public static void main(String[] args) throws InterruptedException {
    ThreadPoolExecutor executor =
        new ThreadPoolExecutor(
            2, // 核心线程数
            4, // 最大线程数
            20, // 等待时间
            TimeUnit.SECONDS, // 等待时间单位
            new ArrayBlockingQueue<>(6), // 等待队列,有界队列
            // 总共能容纳10个线程 4+6
            Executors.defaultThreadFactory(), // 线程工厂,默认提供
            // 四种拒绝策略
            // new ThreadPoolExecutor.AbortPolicy() // 默认拒绝策略,丢弃
            new ThreadPoolExecutor.CallerRunsPolicy() //  提交任务的线程自己执行
            // new ThreadPoolExecutor.DiscardOldestPolicy() // 从队列中删除等待最久的
            // new ThreadPoolExecutor.DiscardPolicy()//直接抛弃最新的,不抛出异常
            );
    for (int i = 1; i <= 15; i++) {
      try {
        executor.execute(new Mythread("[zz]" + i));
        Thread.sleep(1000);
      } catch (Exception e) {
        System.out.println(
            "**********异常:exception:" + Thread.currentThread().getName() + "::" + e.getMessage());
        // 若抛异常,则说明触发率策略,此时修改flag,让所有任务执行完毕
        flag = false;
      } finally {
        System.out.println(
            "-1-"
                + i
                + "-正在执行任务的线程数:"
                + executor.getActiveCount()
                + "-当前池中的线程总数:"
                + executor.getPoolSize()
                + "-设置的核心线程数:"
                + executor.getCorePoolSize()
                + "-设置的最大线程数:"
                + executor.getMaximumPoolSize()
                + "-池中达到过的最大线程数:"
                + executor.getLargestPoolSize()
                + "-已经完成任务数:"
                + executor.getCompletedTaskCount()
                + "-等待队伍中的任务数:"
                + executor.getQueue().size());
      }
    }
    System.out.println("=====" + new Date() + "=====");
    for (int i = 1; i <= 10; i++) {
      Thread.sleep(2000);
      System.out.println(
          "-2-"
              + i
              + "-正在执行任务的线程数:"
              + executor.getActiveCount()
              + "-当前池中的线程总数:"
              + executor.getPoolSize()
              + "-设置的核心线程数:"
              + executor.getCorePoolSize()
              + "-设置的最大线程数:"
              + executor.getMaximumPoolSize()
              + "-池中达到过的最大线程数:"
              + executor.getLargestPoolSize()
              + "-已经完成任务数:"
              + executor.getCompletedTaskCount()
              + "-等待队伍中的任务数:"
              + executor.getQueue().size());
      System.out.println("循环:" + i + "=====" + new Date() + "=====");
    }
    // 如果执行到这里flag还是true ,那么说明执行的拒绝策略为 DiscardOldestPolicy 或者
    // 此时把flag设置为false,让所有的线程任务执行完毕
    if (flag) {
      flag = false;
      Thread.sleep(1000);
      System.out.println("=====所有任务都执行完毕后,再次查看线程池的状态=====");
      for (int i = 0; i < 5; i++) {
        System.out.println(">>正在循环<<");

        System.out.println("-----" + new Date() + "-----");
        Thread.sleep(6000);
        System.out.println(
            "-3-"
                + "-正在执行任务的线程数:"
                + executor.getActiveCount()
                + "-当前池中的线程总数:"
                + executor.getPoolSize()
                + "-设置的核心线程数:"
                + executor.getCorePoolSize()
                + "-设置的最大线程数:"
                + executor.getMaximumPoolSize()
                + "-池中达到过的最大线程数:"
                + executor.getLargestPoolSize()
                + "-已经完成任务数:"
                + executor.getCompletedTaskCount()
                + "-等待队伍中的任务数:"
                + executor.getQueue().size());
      }
    }
    executor.shutdown();
  }

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  static class Mythread implements Runnable {

    private String taskName;

    @Override
    public void run() {
      // 如果main线程执行这个任务,说明已经执行了拒绝策略,CallerRunsPolicy,
      // 此时可以把flag设置为false,让所有的线程把任务执行完毕 (因:已经看到了拒绝策略的执行)
      if ("main".equalsIgnoreCase(Thread.currentThread().getName())) {
        flag = false;
      }
      while (flag) {
        // main线程以外的其他线程执行到这里都进入死循环,为了观察线程池如何触发 拒绝策略
      }
      System.out.println(
          "执行完毕thread:" + Thread.currentThread().getName() + "]--[" + "taskName:" + taskName);
    }
  }
}
